/******************************************************************
 * 作者：sipeiliu
 * 邮箱：sipeiliu@163.com
 * 描述：串口调试模块
 * 日期：2023.4.19
 ******************************************************************/
#include "/opt/sighter/inc/uart.h"

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <termios.h>

static struct termios old_cfg; // 原配置
static int fd_uart;            // 串口终端文件描述符
static int ret;                // 函数返回值

/*初始化串口*/
static void uart_init()
{
    /*打开串口终端*/
    fd_uart = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY);
    if (fd_uart < 0)
    {
        perror("open error");
    }
    /*获取串口当前配置参数*/
    ret = tcgetattr(fd_uart, &old_cfg);
    if (ret < 0)
    {
        perror("tcgetattr error");
    }
}

/*配置串口*/
static void uart_cfg(void)
{
    struct termios new_cfg; // 新配置

    /*设置工作模式*/
    memset(&new_cfg, 0x0, sizeof(struct termios)); // 清零
    cfmakeraw(&new_cfg);                           // 设置为原始模式

    /*使能接收*/
    new_cfg.c_cflag |= CREAD;

    /*设置波特率*/
    ret = cfsetspeed(&new_cfg, B115200); // 默认配置为 115200
    if (ret < 0)
    {
        perror("cfsetspeed error");
    }

    /*设置数据位大小*/
    new_cfg.c_cflag &= ~CSIZE; // 将数据位相关的比特位清零
    new_cfg.c_cflag |= CS8;    // 默认数据位大小为8

    /*设置奇偶校验*/
    new_cfg.c_cflag |= ~PARENB; // 关闭奇偶校验
    new_cfg.c_cflag &= ~INPCK;  // 关闭接收数据的校验检查

    /*设置停止位*/
    new_cfg.c_cflag &= ~CSTOPB; // 默认配置为1个停止位

    /*设置MIN和TIME*/
    new_cfg.c_cc[VTIME] = 0; // 超时时间
    new_cfg.c_cc[VMIN] = 1;  // 最少读取的字符数

    /*处理缓冲区*/
    ret = tcflush(fd_uart, TCIOFLUSH); // 清空尚未处理的输入/输出数据
    if (ret < 0)
    {
        perror("tcflush error");
    }

    /*写入配置*/
    ret = tcsetattr(fd_uart, TCSANOW, &new_cfg);
    if (ret < 0)
    {
        perror("tcsetattr error");
    }
}

/*串口调试*/
void *thread_uart(void *arg)
{
    uart_init();  // 初始化串口
    uart_cfg();   // 配置串口
    char buf[4];  // 缓存
    int speed;    // 速度
    int distance; // 距离

    /*输出数据*/
    while (1)
    {
        /*发送速度*/
        speed = global_speed;
        buf[0] = (char)((speed)&0xff);
        buf[1] = (char)((speed >> 8) & 0xff);
        buf[2] = (char)((speed >> 16) & 0xff);
        buf[3] = (char)((speed >> 24) & 0xff);
        write(fd_uart, buf, 4); // 向串口写入速度

        /*发送距离*/
        distance = global_distance;
        buf[0] = (char)((distance)&0xff);
        buf[1] = (char)((distance >> 8) & 0xff);
        buf[2] = (char)((distance >> 16) & 0xff);
        buf[3] = (char)((distance >> 24) & 0xff);
        write(fd_uart, buf, 4); // 向串口写入距离
        sleep(1);               // 间隔1秒钟
    }

    tcsetattr(fd_uart, TCSANOW, &old_cfg); // 恢复到之前的配置
    close(fd_uart);
}
